using System;
using System.Collections.Generic;
using System.Linq;
using DecisionMaking.Domain;
using log4net;

namespace DecisionMaking.BusinessLogic.Algorithms
{
    public class TakeTheBestAlgorithm : IAlgorithm
    {
        private AlgorithmDefinition _definition;

        private static readonly ILog Log = LogManager.GetLogger(typeof(TakeTheBestAlgorithm));

        public AlgorithmResult Execute(Agent agent, IList<Cue> cues, Candidate left, Candidate right)
        {
            short result = 0;
            short cuesUsed = 0;
            short candidatesRecognized = 0;

            // step #1 - recognition principle
            if (agent.Recognizes(left) && !agent.Recognizes(right)) 
            {
              candidatesRecognized = 1;
              cuesUsed = 1;
              result = -1;
            } 
            else if (agent.Recognizes(right) && !agent.Recognizes(left)) 
            {
              candidatesRecognized = 1;
              cuesUsed = 1;
              result = 1;
            } 
            else if (!agent.Recognizes(right) && !agent.Recognizes(left)) 
            {
              candidatesRecognized = 0;
              cuesUsed = 0;
              result = 0;  
            } 
            else 
            {
              candidatesRecognized = 2;
  
              // sort all cues according to their validity, descendingly
              var cueArray = (from c in cues orderby c.GetAttributeValue("Ecological Validity") select c).ToArray();
    
              // step #2 - search for cue values
              foreach (var cue in cueArray)
              {
                  cuesUsed++;
      
                  var leftValue = agent.GetCueValue(left, cue);
                  var rightValue = agent.GetCueValue(right, cue);
      
                  // step #3 - discrimination rule
                  if (leftValue > 0 && rightValue <= 0) 
                  {
                      result = -1;
                      break;
                  } 
                  else if (leftValue <= 0 && rightValue > 0) 
                  {
                      result = 1;
                      break;
                  }
              }
  
              // if we got here without deciding on a result, we couldn't decide between the two candidates      
            }
            return new AlgorithmResult(result, cuesUsed, candidatesRecognized);
            
        }

        public string Validate()
        {
            return null;
        }

        public AlgorithmDefinition GetDefinition()
        {
            return _definition;
        }

        public void SetDefinition(AlgorithmDefinition definition)
        {
            _definition = definition;
        }
    }
}